﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace THO7AlgoritmTimerApplication
{
    public partial class MainForm : Form
    {
        List<VisionAlgorithm> AlgorithmList = new List<VisionAlgorithm>();
        List<VisionAlgorithm> NoiseList = new List<VisionAlgorithm>();
        Stopwatch stopWatch;
        Queue<List<object>> algoritmQueue;


        private Bitmap inputImage;
        private Bitmap outputImage;
        private List<String> fontList = new List<String>();

        #region public getters & setters
        public List<String> FontList
        {
            get { return fontList; }
            set { fontList = value; }
        }


        public Bitmap OutputImage
        {
            get { return outputImage; }
            set
            {
                outputImage = value;
                OutputPictureBox.Image = value;
            }
        }
        #endregion

        public MainForm()
        {
            InitializeComponent();
            AlgoButton.Enabled = false;
            AlgorithmList.Add(new VisionAlgorith_OCR("OCR"));
            //Insert new Algorithms here
            /*          ^
            *          /|\
            *           |
            */


            foreach (VisionAlgorithm vA in AlgorithmList)
            {
                AlgoListBox.Items.Add(vA.Name);
            }
            algoritmQueue = new Queue<List<object>>();
        }

        private void openPictureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            openImage();
        }

        private void openImage()
        {
            OpenFileDialog oFD = new OpenFileDialog();
            oFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            oFD.Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.PNG;)|*.BMP;*.JPG;*.JPEG;*.PNG;";
            oFD.FilterIndex = 1;
            oFD.RestoreDirectory = true;
            if (oFD.ShowDialog() == DialogResult.OK)
            {
                String CurrentFileName = Path.GetFullPath(oFD.FileName);
                inputImage = new Bitmap(CurrentFileName);
                InputPictureBox.Image = inputImage;
            }

        }

        private void AlgoListBox_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void AlgoButton_Click(object sender, EventArgs e)
        {

            if (inputImage != null)
            {
                try
                {

                    InfoLabel.Text = "";
                    int i = 0;
                    foreach (VisionAlgorithm vA in AlgorithmList)
                    {
                        if (AlgoListBox.GetItemChecked(i))
                            algoritmQueue.Enqueue(new List<object> { vA, inputImage, 1 });
                        i++;
                    }
                    runQueuedAlgorithms();


                }
                catch
                {
                    InfoLabel.Text += "Can't run that number of times\n";
                }
            }

        }

        private bool runQueuedAlgorithms()
        {
            if (algoritmQueue.Count > 0)
            {
                List<object> algArgs = algoritmQueue.Dequeue();
                InfoLabel.Text += "Start running " + ((VisionAlgorithm)(algArgs.ElementAt(0))).Name + "...\n";
                startAlgThread(algArgs);
                return true;
            }
            return false;
        }

        private void OutputPictureBox_DoubleClick(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                Form ipForm = new ImagePreviewForm(new Bitmap(OutputPictureBox.Image));
                ipForm.Show();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void OutputToInputButton_Click(object sender, EventArgs e)
        {
            if (OutputPictureBox.Image != null)
            {
                inputImage = new Bitmap(OutputPictureBox.Image);
                InputPictureBox.Image = inputImage;
                OutputPictureBox.Image = null;
            }
        }


        private void ClearButton_Click(object sender, EventArgs e)
        {

            InfoLabel.Text = "";
        }

        private void backgroundAlgorithmWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("Error: " + e.Error.Message);
            }
            else if (e.Cancelled)
            {
                InfoLabel.Text += "...Cancelled\n";
            }
            else
            {
                double elapsedms = Convert.ToDouble(stopWatch.ElapsedMilliseconds);
                //double average = elapsedms / Convert.ToDouble(textBoxRuns.Text);

                InfoLabel.Text += e.Result + ", took: " + elapsedms + " ms\n"; // over " + textBoxRuns.Text + " times\n";
                //InfoLabel.Text += "==> average: " + average + "ms\n";
                OutputPictureBox.Image = outputImage;
                if (checkBoxSaveOutputImages.Checked)
                {
                    outputImage.Save(e.Result.ToString() + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                }
            }
            if (!runQueuedAlgorithms())
            {
                DateTime current = DateTime.Now;
                String curStr = current.ToString("yyyy-MM-dd__HH-mm-ss");
                String fileName = curStr + "_results.txt";
                FileStream fs = new FileStream(fileName, FileMode.Create);
                StreamWriter outfile = new StreamWriter(fs, Encoding.UTF8);
                outfile.Write(InfoLabel.Text.ToString());
                outfile.Flush();
                outfile.Close();
                fs.Close();

                EnableAllInputs(true);

                //MessageBox.Show("Done...\nResults saved to: " + fileName);
            }
        }

        private void backgroundAlgorithmWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            System.ComponentModel.BackgroundWorker worker;
            worker = (System.ComponentModel.BackgroundWorker)sender;
            List<object> argList = (List<object>)e.Argument;
            VisionAlgorithm visAlg = (VisionAlgorithm)argList.ElementAt(0);
            Bitmap InputImage = (Bitmap)argList.ElementAt(1);
            int numberOfRuns = (int)argList.ElementAt(2);
            stopWatch.Start();
            bool skip = false;

            if (visAlg.GetType() == typeof(VisionAlgorith_OCR))
            {
                VisionAlgorith_OCR _visAlg = new VisionAlgorith_OCR("");
                _visAlg.FontList = this.fontList;
                visAlg = _visAlg;
               
            }
           
                try
                {

                    for (int i = 1; i < numberOfRuns; i++)
                    {

                        visAlg.DoAlgorithm(InputImage);

                    }
                    outputImage = visAlg.DoAlgorithm(InputImage);
                    e.Result = visAlg.Name + " finished successfully";
                }
                catch
                {
                    e.Cancel = true;
                }
                finally
                {
                    stopWatch.Stop();
                }
          

        }

        private void EnableAllInputs(bool state)
        {
            openPictureToolStripMenuItem.Enabled = state;
            AlgoButton.Enabled = state;
            AlgoListBox.Enabled = state;
            OutputToInput.Enabled = state;
            InputPictureBox.Enabled = state;
        }

        private void startAlgThread(List<object> argList)
        {
            stopWatch = new Stopwatch();
            EnableAllInputs(false);
            backgroundAlgorithmWorker.RunWorkerAsync(argList);
        }





        private void InputPictureBox_Click(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog oFD = new OpenFileDialog();
            oFD.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
            oFD.Filter = "Font Files(*.TTF;)|*.TTF;";
            oFD.FilterIndex = 1;
            oFD.RestoreDirectory = true;
            if (oFD.ShowDialog() == DialogResult.OK)
            {
                String CurrentFileName = Path.GetFullPath(oFD.FileName);
                fontList.Add(CurrentFileName);
                AlgoButton.Enabled = true;
            }

        }

        private void button2_Click(object sender, EventArgs e)
        {
            AlgoButton.Enabled = false;
            fontList.Clear();
        }









    }
}
